import { SessionConfigManager } from './session-config-manager'
import { createHash, randomUUID } from 'crypto'
import * as path from 'path'
import * as os from 'os'
import fs from 'fs-extra'

export interface EnhancedSessionContext {
  workingDirectory?: string
  userHome?: string
  userName?: string
  projectName?: string
  processId?: number
  sessionId?: string // 允许手动指定会话ID
}

export interface ProcessSessionInfo {
  sessionId: string
  processId: number
  userId: string
  projectPath: string
  createdAt: string
  lastUsedAt: string
  isActive: boolean
}

export class EnhancedSessionManager {
  private static sessionCache = new Map<string, SessionConfigManager>()
  private static processSessionsPath = path.join(os.homedir(), '.funi-mcp', 'process-sessions.json')
  private static lockPath = path.join(os.homedir(), '.funi-mcp', 'process-sessions.lock')
  private static isWriting = false

  /**
   * 获取会话管理器（支持进程级隔离）
   */
  static async getSessionManager(context?: EnhancedSessionContext): Promise<{
    manager: SessionConfigManager
    sessionInfo: ProcessSessionInfo
  }> {
    const sessionKey = await this.generateSessionKey(context)
    
    // 从缓存获取
    if (this.sessionCache.has(sessionKey)) {
      const manager = this.sessionCache.get(sessionKey)!
      await manager.loadConfig()
      const sessionInfo = await this.getProcessSessionInfo(sessionKey)
      return { manager, sessionInfo }
    }

    // 创建新的会话管理器
    const { userId, projectPath, sessionId } = this.extractSessionInfo(context)
    const manager = new SessionConfigManager(sessionId, userId, projectPath)
    await manager.loadConfig()
    
    // 缓存管理器
    this.sessionCache.set(sessionKey, manager)
    
    // 注册进程会话
    const sessionInfo = await this.registerProcessSession(sessionKey, {
      sessionId: manager.getSessionId(),
      userId,
      projectPath
    }, context?.processId)
    
    return { manager, sessionInfo }
  }

  /**
   * 生成会话键（包含进程隔离）
   */
  private static async generateSessionKey(context?: EnhancedSessionContext): Promise<string> {
    const workingDir = context?.workingDirectory || process.cwd()
    const userName = context?.userName || os.userInfo().username
    const processId = context?.processId || process.pid

    // 如果手动指定了会话ID，直接使用
    if (context?.sessionId) {
      return `manual-${context.sessionId}-${processId}`
    }

    // 始终包含进程ID以确保隔离
    return createHash('md5')
      .update(`${userName}-${workingDir}-${processId}-${Date.now()}-${Math.random()}`)
      .digest('hex')
      .substring(0, 16)
  }

  /**
   * 提取会话信息
   */
  private static extractSessionInfo(context?: EnhancedSessionContext): {
    userId: string
    projectPath: string
    sessionId?: string
  } {
    const workingDir = context?.workingDirectory || process.cwd()
    const userName = context?.userName || os.userInfo().username

    return {
      userId: `${userName}@${os.hostname()}`,
      projectPath: workingDir,
      sessionId: context?.sessionId
    }
  }

  /**
   * 注册进程会话
   */
  private static async registerProcessSession(
    sessionKey: string,
    info: { sessionId: string; userId: string; projectPath: string },
    processId?: number
  ): Promise<ProcessSessionInfo> {
    const processSessions = await this.loadProcessSessions()
    const actualProcessId = processId || process.pid
    
    const sessionInfo: ProcessSessionInfo = {
      sessionId: info.sessionId,
      processId: actualProcessId,
      userId: info.userId,
      projectPath: info.projectPath,
      createdAt: new Date().toISOString(),
      lastUsedAt: new Date().toISOString(),
      isActive: true
    }

    processSessions[sessionKey] = sessionInfo
    await this.saveProcessSessions(processSessions)
    
    return sessionInfo
  }

  /**
   * 获取进程会话信息
   */
  private static async getProcessSessionInfo(sessionKey: string): Promise<ProcessSessionInfo> {
    const processSessions = await this.loadProcessSessions()
    const sessionInfo = processSessions[sessionKey]
    
    if (sessionInfo) {
      // 更新最后使用时间
      sessionInfo.lastUsedAt = new Date().toISOString()
      await this.saveProcessSessions(processSessions)
    }
    
    return sessionInfo
  }

  /**
   * 获取活跃的项目会话
   */
  private static async getActiveProjectSessions(
    projectPath: string,
    userName: string
  ): Promise<ProcessSessionInfo[]> {
    const processSessions = await this.loadProcessSessions()
    const userId = `${userName}@${os.hostname()}`
    
    return Object.values(processSessions).filter(session => 
      session.projectPath === projectPath &&
      session.userId === userId &&
      session.isActive &&
      this.isProcessAlive(session.processId)
    )
  }

  /**
   * 检查进程是否存活
   */
  private static isProcessAlive(pid: number): boolean {
    try {
      process.kill(pid, 0)
      return true
    } catch (error) {
      return false
    }
  }

  /**
   * 加载进程会话数据
   */
  private static async loadProcessSessions(): Promise<Record<string, ProcessSessionInfo>> {
    try {
      if (await fs.pathExists(this.processSessionsPath)) {
        const data = await fs.readFile(this.processSessionsPath, 'utf-8')
        return JSON.parse(data)
      }
    } catch (error) {
      console.warn('加载进程会话数据失败:', error)
    }
    return {}
  }

  /**
   * 保存进程会话数据（带锁机制）
   */
  private static async saveProcessSessions(sessions: Record<string, ProcessSessionInfo>): Promise<void> {
    // 简单的锁机制，避免并发写入
    while (this.isWriting) {
      await new Promise(resolve => setTimeout(resolve, 10))
    }

    this.isWriting = true

    try {
      await fs.ensureDir(path.dirname(this.processSessionsPath))

      // 使用临时文件写入，然后原子性重命名
      const tempPath = this.processSessionsPath + '.tmp'
      await fs.writeFile(tempPath, JSON.stringify(sessions, null, 2), 'utf-8')
      await fs.move(tempPath, this.processSessionsPath, { overwrite: true })
    } catch (error) {
      console.warn('保存进程会话数据失败:', error)
    } finally {
      this.isWriting = false
    }
  }

  /**
   * 清理死进程的会话
   */
  static async cleanupDeadProcessSessions(): Promise<number> {
    const processSessions = await this.loadProcessSessions()
    let cleanedCount = 0

    for (const [sessionKey, sessionInfo] of Object.entries(processSessions)) {
      if (!this.isProcessAlive(sessionInfo.processId)) {
        delete processSessions[sessionKey]
        cleanedCount++
      }
    }

    if (cleanedCount > 0) {
      await this.saveProcessSessions(processSessions)
    }

    return cleanedCount
  }

  /**
   * 列出所有活跃的进程会话
   */
  static async listActiveProcessSessions(): Promise<ProcessSessionInfo[]> {
    const processSessions = await this.loadProcessSessions()
    
    return Object.values(processSessions).filter(session => 
      session.isActive && this.isProcessAlive(session.processId)
    )
  }

  /**
   * 获取项目会话统计
   */
  static async getProjectSessionStats(): Promise<Array<{
    projectPath: string
    userId: string
    sessionCount: number
    sessions: ProcessSessionInfo[]
  }>> {
    const activeSessions = await this.listActiveProcessSessions()
    const projectMap = new Map<string, ProcessSessionInfo[]>()

    // 按项目分组
    for (const session of activeSessions) {
      const key = `${session.userId}:${session.projectPath}`
      if (!projectMap.has(key)) {
        projectMap.set(key, [])
      }
      projectMap.get(key)!.push(session)
    }

    // 转换为统计格式
    return Array.from(projectMap.entries()).map(([key, sessions]) => {
      const [userId, projectPath] = key.split(':')
      return {
        projectPath,
        userId,
        sessionCount: sessions.length,
        sessions
      }
    })
  }

  /**
   * 智能检测项目信息（增强版）
   */
  static async detectProjectInfo(context?: EnhancedSessionContext): Promise<{
    userId: string
    projectPath: string
    projectName: string
    sessionKey: string
    hasMultipleSessions: boolean
    sessionCount: number
  }> {
    const workingDir = context?.workingDirectory || process.cwd()
    const userName = context?.userName || os.userInfo().username
    const projectName = context?.projectName || path.basename(workingDir)
    const sessionKey = await this.generateSessionKey(context)

    // 检查同项目的会话数量
    const projectSessions = await this.getActiveProjectSessions(workingDir, userName)

    return {
      userId: `${userName}@${os.hostname()}`,
      projectPath: workingDir,
      projectName,
      sessionKey,
      hasMultipleSessions: projectSessions.length > 0,
      sessionCount: projectSessions.length
    }
  }

  /**
   * 清理缓存
   */
  static clearCache(): void {
    this.sessionCache.clear()
  }

  /**
   * 获取缓存状态
   */
  static getCacheStatus(): {
    cacheSize: number
    sessions: Array<{
      sessionKey: string
      sessionId: string
      userId?: string
      projectPath?: string
    }>
  } {
    const sessions = Array.from(this.sessionCache.entries()).map(([key, manager]) => ({
      sessionKey: key,
      sessionId: manager.getSessionId(),
      userId: manager.getSessionInfo().userId,
      projectPath: manager.getSessionInfo().projectPath
    }))

    return {
      cacheSize: this.sessionCache.size,
      sessions
    }
  }
}
